﻿#define _CRT_SECURE_NO_WARNINGS 1
#include"ThreadCache.h"
#include"CentralCache.h"
//申请和释放空间
void* ThreadCache::Allocate(size_t size)
{
	assert(size < MAX_BYTES);
	size_t alignsize = SizeClass::Roundup(size);
	size_t index = SizeClass::Index(size);
	if (!_freeLists[index].Empty())
	{
		return _freeLists[index].Pop();
	}
	else {
		return FetchFromCentralCache(index, alignsize);
	}
}
void ThreadCache::Deallocate(void* ptr, size_t size)
{
	assert(ptr);
	assert(size < MAX_BYTES);
	//找出桶 插入
	size_t index = SizeClass::Index(size);
	_freeLists[index].Push(ptr);
	//当链表长度大于一次批量申请的内存 就还一段list给central cache
	if (_freeLists[index].Size() >= _freeLists[index].MaxSize())
	{
		ListTooLong(_freeLists[index], size);
	}
}

// 释放对象时，链表过⻓时，回收内存回到中⼼缓存
void ThreadCache::ListTooLong(FreeList& list, size_t size)
{
	void* start = nullptr;
	void* end = nullptr;
	list.PopRange(start, end, list.MaxSize());
	CentralCache::GetInstance()->ReleaseListToSpans(start, size);
}

//从中心缓存拿
void* ThreadCache::FetchFromCentralCache(size_t index, size_t size) {
	//慢开始反馈调节算法
	size_t batchNum = std::min(_freeLists[index].MaxSize(),SizeClass::NumMoveSize(size));
	if (_freeLists[index].MaxSize() == batchNum)
	{
		_freeLists[index].MaxSize() += 1;
	}
	void* start = nullptr;
	void* end = nullptr;
	//实际能从CentralCache中获取到的对象数
	//选出合适的对象申请数，慢开始
	size_t actualNum = CentralCache::GetInstance()->FetchRangeObj(start, end, batchNum, size);
	//将从CentralCache中获取到的对象数给ThreadCache
	assert(actualNum >= 1);
	if (actualNum == 1)
	{
		assert(start==end);
		return start;
	}
	else
	{
		//将第一个对象返回以外，还需要将剩下的对象挂到threadcache对应的哈希桶中
		_freeLists[index].PushRange(NextObj(start), end,actualNum-1);
		return start;  
	}
}